from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from core.models import Level, Member, Address
from shop.models import DessertItem, Sale
from settings import LOGIN_URL
import datetime
import re

is_member = lambda u: Member.objects.filter(user=u).exists()

def member_only(view_func):
    def _wrapper(request, *args, **kwargs):
        user = request.user
        if user.is_authenticated() and is_member(user):
            return view_func(request, *args, **kwargs)
        return redirect(LOGIN_URL)

    return _wrapper

def potential_member_only(view_func):
    def _wrapper(request, *args, **kwargs):
        user = request.user
        if user.is_authenticated() and not is_member(user):
            logout(request)
        return view_func(request, *args, **kwargs)

    return _wrapper

@potential_member_only
def index(request):
    items = DessertItem.objects.order_by('-pk')[:6]
    feature_side = items[1:3]
    feature_below = items[3:6]
    params = {
        'feature': items[0],
        'feature_side': feature_side,
        'feature_below': feature_below,
    }
    return render_to_response('index.html', params, context_instance=RequestContext(request))

def signin(request):
    if request.method != 'POST':
        if request.GET.get('from', '') == 'register':
            return render_to_response('reg-signin.html', {'signin': True, 'message': 'Thank you for registration!'})
        return render_to_response('reg-signin.html', {'signin': True})

    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)

    if user and is_member(user):
        login(request, user)
        return redirect('/')
    else:
        return render_to_response('reg-signin.html', {'signin': True, 'message': 'Your username and password combination is invalid.'})

def signout(request):
    logout(request)
    return redirect('/')

def _validate_email(email_string):
    from django.core.validators import validate_email
    from django.core.validators import ValidationError
    try:
        validate_email(email_string)
        return True
    except ValidationError:
        return False

def validate_registration(registration):
    user = registration.get('username', '')
    if not user or len(user) < 4:
        print 'failed at user'
        return False

    email = registration.get('email', '')
    if not email or not _validate_email(email):
        print 'failed at email'
        return False

    pass1 = registration.get('password', '')
    pass2 = registration.get('password2', '')
    if not pass1 or pass1 != pass2:
        print 'failed at pass'
        return False

    name = registration.get('name', '')
    if not name:
        print 'failed at name'
        return False

    birth = registration.get('birthday', '')
    if re.match(r'(\d{4})-(\d{2})-(\d{2})', birth) == None:
        print 'failed at birth'
        return False

    country = registration.get('country', '')
    state = registration.get('state', '')
    city = registration.get('city', '')
    street = registration.get('street', '')
    if not country or not state or not city or not street:
        print 'failed at cscs'
        return False
        
    return True

def extract_date(date_string):
    result = re.match(r'(\d{4})-(\d{2})-(\d{2})', date_string)
    if not result:
        # not match
        return None
    year, month, day = [int(g) for g in result.groups()]
    return datetime.date(year, month, day)

def create_user(registration):
    # create User
    user = User.objects.create_user(registration['username'], registration['email'], registration['password'])
    user.save()

    # create MemberInfo
    level = Level.objects.get(name='Basic')
    birthday = extract_date(registration['birthday'])
    today = datetime.date.today()
    member = Member.objects.create(
        user = user,
        level = level,
        name = registration['name'],
        gender = registration['gender'],
        birthday = birthday,
        register_date = today,
        expire_date = today,
    )
    member.save()

    # create Address
    addr = Address.objects.create(
        member = member,
        country = registration['country'],
        state = registration['state'],
        city = registration['city'],
        street = registration['street'],
    )
    addr.save()

def register(request):
    if request.method == 'POST':
        if not validate_registration(request.POST):
            return render_to_response('reg-signin.html')

        # safe to create user now
        create_user(request.POST)
        return redirect('/signin?from=register')
    else:
        return render_to_response('reg-signin.html')

@member_only
def account(request):
    member = request.user.info
    recent_bought_items = Sale.recent_items(member, from_reservation=False)[:4]
    recent_reserved_items = Sale.recent_items(member, from_reservation=True)[:4]
    params = {
        'bought_items': recent_bought_items,
        'reserved_items': recent_reserved_items,
    }
    return render_to_response('account.html', params, context_instance=RequestContext(request))

def reactivate_member(member):
    # set the expiration date to a year later from today
    one_year = datetime.timedelta(days=365)
    member.expire_date += one_year

RECHAEGE_PRESET_VALUES = [100, 200, 300, 400]
@member_only
def recharge(request):
    params = {'recharge_values': RECHAEGE_PRESET_VALUES}
    if request.method == 'POST':
        try:
            recharge_value = int(request.POST['recharge-value'])

            if recharge_value in RECHAEGE_PRESET_VALUES:
                member = request.user.info
                member.balance += recharge_value
                if not member.is_active():
                    # reactivate the user
                    reactivate_member(member)
                member.save()
                return redirect('/account')
            # wrong value
            params['message'] = 'Please select a preset value'
        except ValueError:
            params['message'] = 'Please provide a corrent value'

        return render_to_response('recharge.html', params, context_instance=RequestContext(request))
    # GET method
    return render_to_response('recharge.html', params, context_instance=RequestContext(request))
